
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Adicao de 2 numeros entrados pelo teclado, com saida em video
;
; Aritmetica modulo 16 (sinalizada)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


SEGMENT code       ; segmento de codigo
..start:           ; ponto de entrada


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Trecho inicial - Leitura dos digitos pelo teclado (4 bits)

  mov  ax, data    ; seta segmento de dados
  mov  ds, ax

  call LeEntrada   ; le primeiro numero
  mov  bl, al      ; bl <- 1o digito

  mov  ah, 2       ; imprime caracter '+' (soma)
  mov  dl, '+'   
  int  0x21

  call LeEntrada   ; le segundo numero
  mov  bh, al      ; bh <- 2o digito

  add  bl, bh      ; soma os dois digitos -> resultado em bl
  and  bl, 0x0f    ; limpa nibble alto (aritmetica modulo 16)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Insira seu codigo neste espaco


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Trecho final - Escrita do numero no video (8 bits)

  mov  dl, '='     ; imprime caracter '=' (resultado)
  mov  ah, 2
  int  0x21

  mov  dh, bl
  call ImprimeResultado

Fim:
  mov ax, 0x4C00   ; retorna ao DOS
  int 0x21


; FIM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUBROTINAS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Subrotina: LeEntrada
;
; Essa rotina le do teclado um digito (supostamente um numero de 0-9) 
; e o transforma em sua representacao binaria. Se o caracter '-' for 
; encontrado, a rotina transforma o proximo digito (numero) em sua 
; representacao em complemento de 2. O resultado eh retornado no 
; registrador al (nibble baixo).
;
; Registradores destruidos: ax
;
; Entrada: (nao se aplica)
;
; Saida:  al (nibble menos significativo) = digito (numero) em binario 
; (se '-', o valor negativo estah em  complemento de 2)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

LeEntrada:
  mov  ah, 1       ; le primeiro digito (resultado em al)
  int  0x21

  cmp  al, '-'     ; numero negativo?
  jnz  SemSinal

; numero com sinal, transforma em sua representacao em complemento de 2
  mov  ah, 1       ; pega proximo digito (resultado em al)
  int  0x21

  cmp  al, '0'      ; se entrada == -0, considera-se como 0
  jz   SemSinal

  sub  al, 0x30    ; converte de ASCII para binario
  not  al          ; complemento de 2 (inverte e soma 1)
  add  al, 1
  and  al, 0x0f    ; limpa nibble alto (aritmetica modulo 16)
  cmp  al, 8
  jl   EntradaInvalida

SemSinal:          
  sub  al, 0x30    ; converte de ASCII para binario
  cmp  al, 7
  jg   EntradaInvalida

  ret

EntradaInvalida:

  mov  dx, EntradaErro  ; mostra mensagem de erro e encerra
  mov  ah, 9
  int  0x21  
  jmp  Fim




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Subrotina: ImprimeResultado
; 
; Essa rotina imprime um numero binario na faixa de [-8..7], codificado em complemento de 2,
; presente no registrador dh.
;
; Registradores destruidos: ds, dx, ax
;
; Entrada: dh = numero em complemento de 2 (8-bit)
;
; Saida: (nao se aplica)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ImprimeResultado:
  cmp  dh, 7           ; checa se numero >= -8 e <= 7
  jg   Invalido
  cmp  dh, -8
  jl   Invalido

  ; numero valido
  cmp  dh, 0           ; numero negativo?
  jge  ImprimeDigito

; numero negativo, imprime '-'
  mov  dl, '-'
  mov  ah, 2
  int  0x21

; numero negativo, usa o complemento de 2
  not  dh 
  add  dh, 1


ImprimeDigito:
  add  dh, 0x30        ; converte de binario para ASCII

  mov  dl, dh
  mov  ah, 2           ; imprime caracter ASCII presente no registrador DL
  int  0x21
  ret

Invalido:
  mov  dx, ResultadoErro
  mov  ah, 9
  int  0x21  

  ret



SEGMENT data           ; segmento de dados  
ResultadoErro DB ' *** resultado invalido! *** ', 13, 10, '$'
EntradaErro   DB 13, 10, ' *** Entrada invalida! *** ', 13, 10, '$'

SEGMENT stack stack    ; segmento de pilha
RESB 64
stacktop:
